package io.kiki.sba.registry.server.metadata.resource.filter;

import com.fasterxml.jackson.core.type.TypeReference;
import io.kiki.sba.registry.common.model.console.PersistenceData;
import io.kiki.sba.registry.server.metadata.provide.data.ProvideDataService;
import io.kiki.sba.registry.store.api.DBResponse;
import io.kiki.sba.registry.store.api.OperationStatus;
import io.kiki.sba.registry.util.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.Set;

import static io.kiki.sba.registry.common.model.constants.ValueConstants.ADMIN_API_TOKEN_DATA_ID;


@Provider
@AuthRestController
@Priority(Priorities.USER)
public class AuthRestFilter implements ContainerRequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(AuthRestFilter.class);

    @Autowired
    private ProvideDataService provideDataService;

    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {
        boolean authAllow;
        DBResponse<PersistenceData> queryResponse = provideDataService.queryProvideData(ADMIN_API_TOKEN_DATA_ID);
        if (queryResponse.getOperationStatus() == OperationStatus.notfound || StringUtils.isBlank(queryResponse.getEntity().getData())) {
            authAllow = true;
        } else {
            authAllow = false;
            Set<String> tokens = JsonUtils.read(queryResponse.getEntity().getData(), new TypeReference<Set<String>>() {
            });
            if (!CollectionUtils.isEmpty(tokens) && tokens.contains(getAuthToken(containerRequestContext))) {
                authAllow = true;
            }
        }
        if (!authAllow) {
            Response response = Response.status(Response.Status.UNAUTHORIZED).header("reason", "auth check failed!").build();
            logger.error("[filter] url: %s, auth check fail!", containerRequestContext.getUriInfo().getPath());
            containerRequestContext.abortWith(response);
        }
    }

    public String getAuthToken(ContainerRequestContext context) {
        String token = context.getHeaderString("x-apiauth-token");
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        return "unknown";
    }
}
